package org.xserver.component.core.websocket;


import java.util.Collection;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.handler.codec.http.websocketx.CloseWebSocketFrame;
import org.jboss.netty.handler.codec.http.websocketx.WebSocketFrame;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.xserver.common.util.MessageUtils;
import org.xserver.component.json.JsonManager;
import org.xserver.component.spring.SpringUtil;

import com.business.api.Constant;
import com.business.bean.DefaultJsonResponse;
import com.fasterxml.jackson.core.JsonProcessingException;
/**
 * 
 * @author Idol
 *
 * @param <T>
 */
@Component
public abstract class KeepAliveWebsocketResolver<T extends WebSocketFrame> implements WebSocketFrameResolver<WebSocketFrame> {

	private static final Logger log = LoggerFactory
			.getLogger(KeepAliveWebsocketResolver.class);

    //轮训时间 检测过期连接 定时器定时时间
    private final static int SCHEDULE_SECONDS = 30;
    private static ScheduledExecutorService scheduleService = Executors.newScheduledThreadPool(1);

    /*标记状态*/
    private static volatile boolean isSent = true;

    /** 允许保活次数， 超过这个数值认为失联，清理连接**/
    private static volatile int MAX_RE_PING = 5;

    static{
              scheduleService.scheduleAtFixedRate(new Runnable() {
                  @Override
                  public void run() {
                	  log.debug("  保活，清理线程启动.... ");
                      try {
                              if (isSent) {
                                  isSent = false;
                                  //定时发送心跳
                                  sendPingMessageToAll();
                                  sendTestMessageToAll();
                              } else {
                                  isSent = true;
                                  clearNotPingPongMessage();
                              }
                      } catch (Exception e) {
                    	  log.error("",e);
                      }
                  }
              } , 1L , SCHEDULE_SECONDS , TimeUnit.SECONDS);

    }

    /*
        * 给所有客户端发送ping 消息
        *
        * */
    public static void sendPingMessageToAll(){
        WebSocketCacheManager webSocketCacheManager = (WebSocketCacheManager) SpringUtil.getBean(WebSocketCacheManager.class);
        Collection<WebSocketClient> clients = webSocketCacheManager.getAllClients();
        if (clients != null) {
            for (WebSocketClient client : clients) {
                MessageUtils.sendPingMessage(client);
                webSocketCacheManager.putPingClient(client.getChannelHandlerContext().getChannel().getId().toString());
            }
        }
    }
    
    /*
     * 给所有客户端发送ping 消息
     *
     * */
 public static void sendTestMessageToAll(){
     WebSocketCacheManager webSocketCacheManager = (WebSocketCacheManager) SpringUtil.getBean(WebSocketCacheManager.class);
     Collection<WebSocketClient> clients = webSocketCacheManager.getAllClients();
     if (clients != null) {
         for (WebSocketClient client : clients) {
        	 DefaultJsonResponse<Object> response = new DefaultJsonResponse<Object>();
        	 response.setCode(Constant.SUCCESS_CODE+"");
 			 response.setMsg("test"+new Date());
             try {
				MessageUtils.sendMessage(client,JsonManager.json(response));
			} catch (JsonProcessingException e) {
				e.printStackTrace();
			}
             webSocketCacheManager.putPingClient(client.getChannelHandlerContext().getChannel().getId().toString());
         }
     }
 }



    /*
    * 清理上次保活操作发送ping 消息得不到反馈的连接
    *
    *
    * */
    public static void clearNotPingPongMessage(){
        WebSocketCacheManager webSocketCacheManager = (WebSocketCacheManager) SpringUtil.getBean(WebSocketCacheManager.class);
        Collection<WebSocketClient> clients = webSocketCacheManager.getPingClients(MAX_RE_PING);
        if (clients != null) {
            for (WebSocketClient client : clients) {
                Channel channel = client.getChannelHandlerContext().getChannel();
                if (channel.isOpen()) {
                    client.getHandshaker().close(channel , new CloseWebSocketFrame());
                }
                client.setClosed(true);
                webSocketCacheManager.removeWebSocketClient(channel.getId().toString());
            }
        }
    }

    /*
    *
    * 收到关闭请求删除相应客户端
    * */
    public void doHandleRequest(ChannelHandlerContext ctx, Object msg, WebSocketClient webSocketClient) {
        WebSocketCacheManager webSocketCacheManager = (WebSocketCacheManager) SpringUtil.getBean(WebSocketCacheManager.class);
        //每次接收到前端数据
        if (!CloseWebSocketFrame.class.equals(webSocketClient.getClass())) {
            webSocketCacheManager.removePingClient(ctx.getChannel().getId().toString());
        } else {
            webSocketCacheManager.removeWebSocketClient(ctx.getChannel().getId().toString());
        }
    }


	
	
}
